﻿/**
 * @file std_bitset.inl
 * Copyright (c) 2024 Gaaagaa. All rights reserved.
 * 
 * @author  : Gaaagaa
 * @date    : 2024-08-28
 * @version : 1.0.0.0
 * @brief   : 定义 位集（位图） 操作类 内部相关数据类型、常量、宏 等。
 */

/**
 * The MIT License (MIT)
 * Copyright (c) Gaaagaa. All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef __STD_BITSET_INL__
#define __STD_BITSET_INL__

#ifndef __STD_BITSET_H__
#error "Please include std_bitset.h before this file."
#endif // __STD_BITSET_H__

#include "std_comm.inl"

////////////////////////////////////////////////////////////////////////////////
// xstd_bitset_t 的相关数据定义

/** 定义 xstd_bitset_t 位缓存数组 使用的 字类型 */
typedef xbs_size_t   xbs_word_t;

/** 定义 位缓存 的 数据指针类型 */
typedef xbs_word_t * xbs_wptr_t;

/**
 * @struct xstd_bitset_t
 * @brief  位集合 结构体类型。
 */
typedef struct xstd_bitset_t
{
    /**
     * @brief 节点类型的上下文描述信息。
     * @note 
     * 注意，此处有两个字段用于别的用途：
     * 1. 以 xstd_ectxt.xstd_etype 字段 作为 位缓存的容量，
     *    其按位数量计，且与 sizeof(xbs_word_t) * 8 对齐。
     * 2. 用 xstd_ectxt.xstd_esize 字段 记录 已标识位 的数量。
     */
    xstd_context_t xstd_ectxt;

    xbs_wptr_t xbs_bits; ///< 位缓存
} xstd_bitset_t;

////////////////////////////////////////////////////////////////////////////////
// xstd_bitset_t 的相关操作宏函数

//====================================================================

#define XBS_ECTXT(xbs_this)   XSTD_ECTXT(xbs_this)
#define XBS_ETYPE(xbs_this)   XSTD_ETYPE(xbs_this)
#define XBS_ESIZE(xbs_this)   XSTD_ESIZE(xbs_this)
#define XBS_ALTOR(xbs_this)   XSTD_ALTOR(xbs_this)

#define XBS_MALLOC(xbs_this, xst_size)            \
            XSTD_MALLOC((xbs_this), (xst_size))

#define XBS_DEALLOC(xbs_this, xmt_mptr)           \
            XSTD_DEALLOC((xbs_this), (xmt_mptr))

#define XBS_ALFROM(xbs_this, xet_dptr, xet_sptr)  \
            XSTD_ALFROM((xbs_this), (xet_dptr), (xet_sptr))

#define XBS_ALMOVE(xbs_this, xet_dptr, xet_sptr)  \
            XSTD_ALMOVE((xbs_this), (xet_dptr), (xet_sptr))

#define XBS_ALDEST(xbs_this, xet_elem)            \
            XSTD_ALDEST((xbs_this), (xet_elem))

#define XBS_ISSAME_TYPE(xbs_lthis, xbs_rthis)     \
            XSTD_ISSAME_TYPE((xbs_lthis), (xbs_rthis))

#define XBS_ECTXT_UPDATE(xbs_this, xbs_ctxt)      \
            XSTD_ECTXT_UPDATE((xbs_this), (xbs_ctxt))

//====================================================================

/** 整字位宽 */
#define XBS_WORD_WIDE               ((xbs_size_t)(sizeof(xbs_word_t) * 8))

/**
 * @brief 
 * 定义 位索引 与 字索引 相互转换时 的 移位数量。
 * @note 
 * 此 宏常量 表达式，等价于求 log2(2^N) 中 N 的值，
 * 其中 2^N = 8 * sizeof(xbs_word_t)，
 * 且 sizeof(xbs_word_t) <= 8 。
 */
#define XBS_IWPOS_SHIFT             ((xbs_size_t)((sizeof(xbs_word_t) >> 1) - ((sizeof(xbs_word_t) >> 1) / 3) + 3))

/** 设置整字所有位为 已标识状态 的 掩码值 */
#define XBS_WORD_MARKED             ((xbs_word_t)-1)

/** 设置整字所有位为 未标识状态 的 掩码值 */
#define XBS_WORD_UNMARKED           ((xbs_word_t)0)

/** 将 位索引 对齐到 整字 起始位置 */
#define XBS_IPOS_WBEGIN(xbs_ipos)   ((xbs_ipos_t)((xbs_ipos) & ~((xbs_ipos_t)(XBS_WORD_WIDE - 1))))

/** 位索引 对应的 字（索引号） */
#define XBS_IPOS_WPOS(xbs_ipos)     ((xbs_size_t)((xbs_ipos) >> XBS_IWPOS_SHIFT))

/** 字（索引号） 对应的 位索引 */
#define XBS_WPOS_IPOS(xbs_wpos)     ((xbs_ipos_t)((xbs_wpos) << XBS_IWPOS_SHIFT))

/** 索引所在 字 的位索引号 */
#define XBS_IPOS_IBIT(xbs_ipos)     (((xbs_size_t)(xbs_ipos)) & (XBS_WORD_WIDE - 1))

/** 由 索引 构建整字的 位掩码值 */
#define XBS_IPOS_MARK(xbs_ipos)     (((xbs_word_t)1) << XBS_IPOS_IBIT(xbs_ipos))

/** 位缓存 容量 */
#define XBS_BITS_SIZE(xbs_this)     XBS_ETYPE(xbs_this)

/** 已标识状态 的 位数量 */
#define XBS_BITS_NSET(xbs_this)     XBS_ESIZE(xbs_this)

/** 位索引 终点 */
#define XBS_IPOS_END(xbs_this)      ((xbs_ipos_t)XBS_BITS_SIZE(xbs_this))

/** 判断 xbs_ipos 位是否已标识 */
#define XBS_ISMARK(xbs_this, xbs_ipos)                      \
    (                                                       \
        ((xbs_this)->xbs_bits[XBS_IPOS_WPOS(xbs_ipos)] &    \
                              XBS_IPOS_MARK(xbs_ipos))      \
        ? XBS_MARKED : XBS_UNMARKED                         \
    )

/** 设置 xbs_ipos 位状态为 已标识 */
#define XBS_MARK(xbs_this, xbs_ipos)                        \
    do                                                      \
    {                                                       \
        XASSERT(!XBS_ISMARK((xbs_this), (xbs_ipos)));       \
        (xbs_this)->xbs_bits[XBS_IPOS_WPOS(xbs_ipos)] |=    \
                             XBS_IPOS_MARK(xbs_ipos);       \
        XBS_BITS_NSET(xbs_this) += 1;                       \
    } while (0)

/** 设置 xbs_ipos 位状态为 未标识 */
#define XBS_UNMARK(xbs_this, xbs_ipos)                      \
    do                                                      \
    {                                                       \
        XASSERT(XBS_ISMARK((xbs_this), (xbs_ipos)));        \
        (xbs_this)->xbs_bits[XBS_IPOS_WPOS(xbs_ipos)] &=    \
                            ~XBS_IPOS_MARK(xbs_ipos);       \
        XBS_BITS_NSET(xbs_this) -= 1;                       \
    } while (0)

/** 反转 单个 位标识状态 */
#define XBS_FLIPI(xbs_this, xbs_ipos)                       \
    do                                                      \
    {                                                       \
        if (XBS_ISMARK((xbs_this), (xbs_ipos)))             \
            XBS_UNMARK((xbs_this), (xbs_ipos));             \
        else                                                \
            XBS_MARK((xbs_this), (xbs_ipos));               \
    } while (0)

/** 获取 xbs_mark 位标识状态的 反转值  */
#define XBS_INVERT_MARK(xbs_mark)   ((xbs_mark) ? XBS_UNMARKED : XBS_MARKED)

//====================================================================

////////////////////////////////////////////////////////////////////////////////

#endif // __STD_BITSET_INL__
